package com.share.four.netty.runtime;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.ReadTimeoutHandler;

import com.share.four.netty.runtime.entity.Request;
import com.share.four.netty.runtime.util.MarshallingCodeCFactory;

public class Client {

	private static Client client = new Client();

	public static Client getInstance(){
		return client;
	}

	private NioEventLoopGroup workerEvert;
	private Bootstrap b;
	private ChannelFuture cf;

	private Client(){
		workerEvert = new NioEventLoopGroup();
		b = new Bootstrap();
		b.group(workerEvert);
		b.channel(NioSocketChannel.class);
		b.option(ChannelOption.SO_KEEPALIVE, true);
		b.option(ChannelOption.SO_BACKLOG, 1024);
		b.option(ChannelOption.SO_RCVBUF, 1*1024*1024);
		b.option(ChannelOption.SO_SNDBUF, 1*1024*1024);
		b.handler(new LoggingHandler(LogLevel.INFO));
		b.handler(new ChannelInitializer<SocketChannel>() {

			@Override
			protected void initChannel(SocketChannel ch) throws Exception {
				ch.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingDecoder());
				ch.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingEncoder());
				//超时handler（当服务器端与客户端在指定时间以上没有任何进行通信，则会关闭响应的通道，主要为减小服务端资源占用）
				ch.pipeline().addLast(new ReadTimeoutHandler(5));
				ch.pipeline().addLast(new ClientHandler());

			}
		});
	}

	public void connect(){
		try {
			this.cf = b.connect("127.0.0.1", 12345).sync();
			System.out.println("client 已连接。。。");
		} catch (Exception e) {
			System.out.println(e);
		}
	}

	public ChannelFuture getChannelFuture(){
		if (this.cf == null) {
			this.connect();
		}
		if (!this.cf.channel().isActive()) {
			this.connect();
		}

		return this.cf;
	}

	public static void main(String[] args) throws Exception {
		final Client c = Client.getInstance();
		ChannelFuture cf = c.getChannelFuture();

		for (int i = 0; i < 3; i++) {
			final Request req = new Request();
			req.setId("" + i);
			req.setName(""+ i);
			req.setRequestMessage("" + i);

			final ChannelFuture write = cf.channel().writeAndFlush(req);
			write.addListeners(new ChannelFutureListener() {

				@Override
				public void operationComplete(ChannelFuture future) throws Exception {
					if (write == future) {
						System.out.println("client 发送： " + req);
					}

				}
			});
			Thread.sleep(4000);
		}

		//平时是阻塞状态，5s之后client与server之间没有数据传输就断开了（channelFuture断开了）。程序就开始往下走了
		cf.channel().closeFuture().sync();
		
		System.out.println("主线程5s后channelFuture状态(active) ：  " + cf.channel().isActive());
		System.out.println("主线程5s后channelFuture状态(open) ：  " + cf.channel().isOpen());

		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					System.out.println("子线程开始。。。");
					ChannelFuture cf = c.getChannelFuture();
					System.out.println("子线程重连后channelFuture状态(active) ：  " + cf.channel().isActive());
					System.out.println("子线程重连后channelFuture状态(open) ：  " + cf.channel().isOpen());
					

					final Request req = new Request();
					req.setId("" + 5);
					req.setName("" + 5);
					req.setRequestMessage("" + 5);

					final ChannelFuture write = cf.channel().writeAndFlush(req);
					write.addListeners(new ChannelFutureListener() {

						@Override
						public void operationComplete(ChannelFuture future) throws Exception {
							if (write == future) {
								System.out.println("client 发送： " + req);
							}

						}
					});

					cf.channel().closeFuture().sync();
					System.out.println("子线程结束。。。 ");
				} catch (InterruptedException e) {
					System.out.println(e);
				}
			}
		}).start();
	}

}
